/**
 * <h3>Class description</h3>
 * <h4>日期处理类</h4>
 *
 * <h4>Special Notes</h4>
 * 
 *
 * @ver 0.1
 * @author Vincent
* 2008-8-11
 */
package com.donghaiair.framework.common.util;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.xml.bind.DatatypeConverter;
import javax.xml.datatype.XMLGregorianCalendar;

public class DateUtil {
	/**
	 * 常用日期格式：yyyy-MM-dd HH:mm:ss
	 */
	public final static String DF_YYYY_MM_DD_24HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
	/**
	 * 常用日期格式：yyyy-MM-dd hh:mm:ss
	 */
	public final static String DF_YYYY_MM_DD_12HH_MM_SS = "yyyy-MM-dd hh:mm:ss";
	/**
	 * 常用日期格式：yyyy-MM-dd
	 */
	public final static String DF_YYYY_MM_DD = "yyyy-MM-dd";
	/**
	 * 常用日期格式：dd/MM/yyyy
	 */
	public final static String DF_DD_MM_YYYY = "dd/MM/yyyy";
	/**
	 * 常用日期格式：dd/MMM/yyyy
	 */
	public final static String DF_DD_MMM_YYYY = "dd/MMM/yyyy";
	/**
	 * 一天中的天数
	 */
	public static long millionSecondsOfDay = 86400000;
	/**
	 * 
	 * 一天中的小时
	 */
	public static long millionSecondsOfHour = 3600000;

	/**
	 * 
	 * 一天中的小时
	 */
	public static long secondsOfHour = 3600;

	/**
	 * 得到两个日期之间的天数,两头不算,取出数据后，可以根据需要再加
	 * 
	 * @author Vincent
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int getDay(Date date1, Date date2) {
		Long d2 = date2.getTime();
		Long d1 = date1.getTime();
		return (int) ((d2 - d1) / millionSecondsOfDay);
	}

	public static int getMonth(Date date1, Date date2) {
		int iMonth = 0;
		int flag = 0;
		try {
			Calendar objCalendarDate1 = Calendar.getInstance();
			objCalendarDate1.setTime(date1);

			Calendar objCalendarDate2 = Calendar.getInstance();
			objCalendarDate2.setTime(date2);

			if (objCalendarDate2.equals(objCalendarDate1))
				return 0;
			if (objCalendarDate1.after(objCalendarDate2)) {
				Calendar temp = objCalendarDate1;
				objCalendarDate1 = objCalendarDate2;
				objCalendarDate2 = temp;
			}
			if (objCalendarDate2.get(Calendar.DAY_OF_MONTH) < objCalendarDate1.get(Calendar.DAY_OF_MONTH))
				flag = 1;

			if (objCalendarDate2.get(Calendar.YEAR) > objCalendarDate1.get(Calendar.YEAR))
				iMonth = ((objCalendarDate2.get(Calendar.YEAR) - objCalendarDate1.get(Calendar.YEAR)) * 12
						+ objCalendarDate2.get(Calendar.MONTH) - flag) - objCalendarDate1.get(Calendar.MONTH);
			else
				iMonth = objCalendarDate2.get(Calendar.MONTH) - objCalendarDate1.get(Calendar.MONTH) - flag;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return iMonth;
	}

	/**
	 * 
	 * 计算2个时间之间的相差小时和分钟数，返回XX小时XX分 注意date1格式为yyyy-MM-dd 注意date2格式为yyyy-MM-dd
	 * 注意time1格式为HH:mm 注意time2格式为HH:mm date1<date2
	 * 
	 * @param date1
	 * @param time1
	 * @param date2
	 * @param time2
	 * @return
	 */
	public static String getHourAndMinute(String date1, String time1, String date2, String time2) {
		Date dateTime1_tmp = DateUtil.parse(date1 + " " + time1, "yyyy-MM-dd HH:mm");
		Date dateTime2_tmp = DateUtil.parse(date2 + " " + time2, "yyyy-MM-dd HH:mm");
		Long d2 = dateTime2_tmp.getTime();
		Long d1 = dateTime1_tmp.getTime();
		int hours = (int) ((d2 - d1) / millionSecondsOfHour);
		int mins = (int) ((d2 - d1) % millionSecondsOfHour);
		mins = mins / 60000;
		return String.valueOf(hours) + ":" + String.valueOf(mins);
	}

	public static String getMiles(Date date1, Date date2) {
		Long d2 = date2.getTime();
		Long d1 = date1.getTime();
		int hours = (int) ((d2 - d1) / 1000);
		return String.valueOf(hours);
	}

	public static Date addMonth(Date date, int months) {
		Calendar c = new GregorianCalendar();
		c.setTime(date);
		c.add(Calendar.MONTH, months);
		return c.getTime();
	}

	/**
	 * 计算日期加天数
	 * 
	 * @author Vincent
	 * @param date
	 * @param days
	 * @return
	 */
	public static Date addDay(Date date, int days) {
		Calendar c = new GregorianCalendar();
		c.setTime(date);
		c.add(Calendar.DAY_OF_MONTH, days);
		return c.getTime();
	}

	public static Date addMinutes(Date date, int minutes) {
		Calendar c = new GregorianCalendar();
		c.setTime(date);
		c.add(Calendar.MINUTE, minutes);
		return c.getTime();
	}

	/**
	 * 根据指定日期格式格式化日期
	 * 
	 * @author Vincent
	 * @param date
	 * @param formater
	 * @return
	 */
	public static String format(Date date, String formater) {
		SimpleDateFormat sdf = new SimpleDateFormat(formater);
		return sdf.format(date);
	}

	/**
	 * 格式化日期
	 * 
	 * @author Vincent
	 * @param date
	 * @param formater
	 * @return
	 */
	public static Date parse(String date, String formater) {
		SimpleDateFormat sdf = new SimpleDateFormat(formater);
		Date result = null;
		try {
			result = sdf.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 根据日期取出是星期几
	 * 
	 * @author Vincent
	 * @param date
	 *            Date
	 * @return int 返回1-7
	 */
	public static int getWeekOfDate(Date date) {
		if (null == date)
			return 0;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return (calendar.get(Calendar.DAY_OF_WEEK) - 1) == 0 ? 7 : calendar.get(Calendar.DAY_OF_WEEK) - 1;
	}

	public static int getMonthOfDate(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.MONTH);
	}

	public static String getMonthEName(Date date) {
		String dayNames[] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
		int t = getMonthOfDate(date);
		return dayNames[t];
	}

	public static String getMonthEName(String strDate, String format) {
		String dayNames[] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
		int t = getMonthOfDate(parse(strDate, format));
		return dayNames[t];
	}

	public static String getWeekTextOfDate(Date date) {
		String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		int t = getWeekOfDate(date);
		if (t == 7)
			t = 0;
		return dayNames[t];
	}

	public static String getWeekTextOfDate(String strDate, String format) {
		String dayNames[] = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		int t = getWeekOfDate(parse(strDate, format));
		if (t == 7)
			t = 0;
		return dayNames[t];
	}

	/**
	 * format "yyyy-MM-dd HH:mm:ss"
	 */
	public static String dateToString(Date date, String format) {
		if (date == null)
			return null;
		SimpleDateFormat formatter = new SimpleDateFormat(format);
		return formatter.format(date).trim();

	}

	/**
	 * format "yyyy-MM-dd HH:mm:ss"
	 */
	public static String dateToString(Date date) {
		if (date == null)
			return null;
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return formatter.format(date).trim();

	}

	/**
	 * 得到给定日期
	 * 
	 * @param date
	 *            给定日期
	 * @param pattern
	 *            给定日期格式
	 * @return Date 给定日期
	 */
	public static Date getDate(String date, String pattern) {

		SimpleDateFormat formatter = new SimpleDateFormat(pattern);
		try {
			return formatter.parse(date);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * XMLGregorianCalendar 转化为特定格式的日期格式 return String
	 */
	public static String XMLGregorianToDate(XMLGregorianCalendar xmlg) {
		GregorianCalendar ca = xmlg.toGregorianCalendar();
		return format(ca.getTime(), "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 根据数字日期如40695.000000，将该日期转换为标准格式日期
	 * 
	 * @param numberDate
	 * @return
	 */
	public static Date parseNumberDate(String numberDate) {
		// 先準備好一個 Calendar 物件, 並將時間歸零
		Calendar calObj = Calendar.getInstance();
		calObj.setTimeInMillis(0L);
		String[] aryDateTime = numberDate.split("\\.");

		// 設定天數
		calObj.set(1900, 0, Integer.parseInt(aryDateTime[0]) - 1);
		if (aryDateTime.length == 2) {
			// 設定時間, 做法同 C# 的 Sample Code
			float f = Float.parseFloat("0." + aryDateTime[1]) * 86400;
			calObj.add(Calendar.SECOND, (int) f);
		}
		// 要用 GMT 格式才能抓到我們要的日期
		// 各位可以比較 toGMTString(), toLocaleString() 和 toString() 的差別
		return calObj.getTime();
	}

	/**
	 * 将XMLGregorianCalendar日期字符串转换成java.util.Date对象
	 * 
	 * @param str
	 * @return
	 */
	public static Date toDate(String str) {
		return DatatypeConverter.parseDate(str).getTime();
	}

	/**
	 * 取Server 系统日期
	 * 
	 * @return
	 */
	public static Date getSystemDate() {
		return Calendar.getInstance().getTime();
	}

	/**
	 * 返回字符串格式日期 D M
	 * 
	 * @param date
	 * @return
	 */
	public static String getDateToString(final Date date) {
		StringBuilder sb = new StringBuilder();
		if (null != date) {
			sb.append(String.format("%te", date) + " ");
			sb.append(String.format(Locale.US, "%tb", date) + " ");
		}
		return sb.toString();
	}

	/**
	 * 返回英文星期
	 * 
	 * @param i
	 *            1 2 3 4 5 6 7
	 * @return
	 */
	public static String getWeekUS(Integer i) {
		if (null == i)
			return null;
		Map<Integer, String> map = new HashMap<Integer, String>();
		map.put(1, "Mon");
		map.put(2, "Tue");
		map.put(3, "Wed");
		map.put(4, "Thu");
		map.put(5, "Fri");
		map.put(6, "Sat");
		map.put(7, "Sun");
		String str = "";
		if (null != i) {
			str = map.get(i);
		}
		return str;
	}

	/**
	 * 将字符串时间转为毫秒
	 * 
	 * @param rexStr
	 * @return
	 */
	public static Long getTimeInMillis(String rexStr) {
		long millis = 0;
		Calendar c = Calendar.getInstance();
		try {
			c.setTime(new SimpleDateFormat("HHmmssS").parse(rexStr));
			millis = c.getTimeInMillis();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return millis;
	}

	public static String getStrTimes(long millis) {
		String hms = "";
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:S");
		hms = sdf.format(millis);
		return hms;
	}

	/**
	 * 获取当前时间
	 * 
	 * @return Date
	 */
	public static Date currentDate() {
		return new Date();
	}

	/**
	 * 获取当前时间：yyyy-MM-dd HH:mm:ss:SS
	 */
	public static long getCurrentDateTimeLong() {
		return Long.valueOf(new java.text.SimpleDateFormat("HHmmss").format(new java.util.Date()));
	}

	/**
	 * 两个时间的时间差 返回 分钟 kangkang提示 别把返回类型Long 改成其他
	 * 
	 * @param date1
	 * @param date2
	 * @return int
	 */
	public static Long subtractTime(Date date1, Date date2) {
		Long minute = 0L;
		try {
			if (date1.getTime() >= date2.getTime()) {
				minute = (date1.getTime() - date2.getTime()) / 1000 / 60;
			}
		} catch (Exception exception) {
			exception.printStackTrace();
		}
		return minute;
	}

	/**
	 * 将字符串转换成日期
	 * 
	 * @param str
	 * @return
	 */
	public static Date StrToDate(String str) {

		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = null;
		try {
			date = format.parse(str);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return date;
	}

	/**
	 * 计算两个日期之间相差的天数
	 * 
	 * @param smdate
	 *            较小的时间
	 * @param bdate
	 *            较大的时间
	 * @return 相差天数
	 * @throws ParseException
	 */
	public static int daysBetween(Date smdate, Date bdate) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			smdate = sdf.parse(sdf.format(smdate));
			bdate = sdf.parse(sdf.format(bdate));
		} catch (ParseException e) {
			e.printStackTrace();
		}

		Calendar cal = Calendar.getInstance();
		cal.setTime(smdate);
		long time1 = cal.getTimeInMillis();
		cal.setTime(bdate);
		long time2 = cal.getTimeInMillis();
		long between_days = (time2 - time1) / (1000 * 3600 * 24);

		return Integer.parseInt(String.valueOf(between_days));
	}

	/**
	 * 获取当前时间 unix截止时间
	 * 
	 * @return int
	 */
	public static int currentDateInt() {
		return Long.valueOf(currentDate().getTime() / 1000l).intValue();
	}

	/**
	 * 获取当前时间，精确到毫秒
	 * 
	 * @return
	 */
	public static String getCurrentTimes() {
		return new java.text.SimpleDateFormat("yyyyMMddHHmmssSSS").format(new java.util.Date());
	}

	/**
	 * 获取上个月
	 * 
	 * @param date
	 * @return
	 */
	public static Date getBeforeMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, -1);
		return cal.getTime();
	}

	public static void main(String args[]) {
		/*
		 * Date d = new Date(); // 月初 System.out.println("月初" +
		 * dateToString(getMonthStart(d))); // 月末 System.out.println("月末" +
		 * dateToString(getMonthEnd(d)));
		 * 
		 * Date date = getMonthStart(d); Date monthEnd = getMonthEnd(d); while
		 * (!date.after(monthEnd)) { System.out.println(dateToString(date));
		 * date = getNext(date); }
		 */

	}

	public static Date getMonthStart(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int index = calendar.get(Calendar.DAY_OF_MONTH);
		calendar.add(Calendar.DATE, (1 - index));
		return calendar.getTime();
	}

	public static Date getMonthEnd(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MONTH, 1);
		int index = calendar.get(Calendar.DAY_OF_MONTH);
		calendar.add(Calendar.DATE, (-index));
		return calendar.getTime();
	}

	public static Date getNext(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, 1);
		return calendar.getTime();
	}

	public static Timestamp getSysTimestamp() {
		return new Timestamp(new Date().getTime());
	}
}
